#include "str_array.h"

#include <stdlib.h>
#include <string.h>

#include "xlog.h"

enum
{
	CAPA = SqStrMaxSize ,
};

int
sq_str_create(sq_str ** str)
{
	*str = malloc(sizeof(sq_str));
	memset(*str, 0, sizeof(sq_str));
	return 0;
}

int
sq_str_clone(const sq_str * a, sq_str ** str)
{
	int ret = 0;

	if ((ret = sq_str_create(str))) {
		return ret;
	}

	(*str)->len = a->len;
	memcpy((*str)->data, a->data, a->len);

	return 0;
}

int
sq_str_substr(const sq_str * a, size_t i, size_t j, sq_str ** str)
{
	int ret = 0;

	if (i >= a->len || i >= a->len || i >= j) {
		return ERR_INDEX;
	}

	if ((ret = sq_str_create(str))) {
		return -1;
	}

	sq_str * s = *str;
	s->len = j - i;
	memcpy(s->data, a->data + i, s->len);

	return 0;
}

int
sq_str_release(sq_str * str)
{
	free(str);

	return 0;
}

int
sq_str_assign(sq_str * str, const char * cstr)
{
	if (strlen(cstr) > CAPA) {
		return ERR_NOMEM;
	}

	str->len = strlen(cstr);
	memcpy(str->data, cstr, str->len);

	return 0;
}

int
sq_str_copy(sq_str * str, const sq_str * a)
{
	if (a->len > CAPA) {
		return ERR_NOMEM;
	}
	memcpy(str->data, a->data, a->len);
	str->len = a->len;
	return 0;
}

int
sq_str_eq(const sq_str * a, const sq_str * b)
{
	if (a->len != b->len) {
		return ERR_NEQ;
	}

	return memcmp(a->data, b->data, a->len) ? ERR_NEQ : 0;
}

int sq_str_cat(sq_str * str, const sq_str * a)
{
	if (str->len + a->len > CAPA) {
		return ERR_NOMEM;
	}

	memcpy(str->data + str->len, a->data, a->len);
	str->len += a->len;

	return 0;
}

int
sq_str_insert(sq_str * str, size_t i, const sq_str * a)
{
	if (str->len + a->len > CAPA) {
		return ERR_NOMEM;
	}

	memcpy(str->data + i + a->len, str->data + i, a->len);
	memcpy(str->data + i, a->data, a->len);
	str->len += a->len;

	return 0;
}

int
sq_str_del(sq_str * s, size_t i, size_t j)
{
	if (i > j) {
		return ERR_INDEX;
	}

	if (i >= s->len) {
		return 0;
	}

	if (j >= s->len) {
		s->len = i + 1;
		return 0;
	}

	memcpy(s->data + i, s->data + j, s->len - j);
	s->len -= j - i;

	return 0;
}

/*
 * TODO : see memmove
 */
int
sq_str_replace(sq_str * s, size_t i, size_t j, const sq_str * a)
{
	if (i > s->len || i >= j) {
		return ERR_INDEX;
	}

	if (j <= s->len - 1) {
		size_t dlen = j - i;
		if (a->len < dlen) {
			size_t delta = dlen - a->len;
			for (int ii = j; ii < s->len; ++ii) {
				s->data[ii - delta] = s->data[ii];
			}
			memcpy(s->data + i, a->data, a->len);
			s->len += a->len - dlen;
			return 0;
		}
		else if (a->len > dlen){
			size_t delta = a->len - dlen;
			for (int ii = s->len - 1; ii >= j; --ii) {
				s->data[ii + delta] = s->data[ii];
			}
			memcpy(s->data + i, a->data, a->len);
			s->len += a->len - dlen;
			return 0;
		}
		else {
			memcpy(s->data + i, a->data, a->len);
			return 0;
		}
	}
	else {
		s->len = i + 1;
		return sq_str_cat(s, a);
	}
}

int
sq_str_display(const sq_str * s)
{
	printf("_");
	for (size_t i = 0; i < s->len; ++i) {
		printf("%c", s->data[i]);
	}
	printf("_\n");

	return 0;
}

int
sq_str_find_repeator(const sq_str * s, const byte ** posi, size_t * max)
{
	*posi = s->data;
	*max = 0;

	const byte * p = s->data;
	const byte * q = p;
	const byte * e = s->data + s->len;
	size_t len = 0;
	for (; p < e; ++p) {
		if (*q == *p) {
			++len;
		}
		else {
			if (len > *max) {
				*posi = q;
				*max = len;
			}
			else {
				q = p;
				len = 1;
			}
		}
	}

	return 0;
}


